/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * DataViewer.java
 *
 * Created on Oct 24, 2009, 2:38:19 PM
 */
package wekinator;

import java.awt.Color;
import java.awt.Component;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;


/**
 *
 * @author rebecca
 */
public class OscSynthConfigurationFrame2 extends javax.swing.JFrame {

    MySynthConfigRenderer renderer = null;
    final OscSynthConfiguration configuration;

    public OscSynthConfigurationFrame2(final OscSynthConfiguration c) {
        initComponents();
        renderer = new MySynthConfigRenderer();
        configuration = c;
        populateTable(configuration);
        checkRemote.setSelected(configuration.isUseRemoteHost());
        textRemoteHost.setText(configuration.getRemoteHostName());
        textOscPort.setText(Integer.toString(configuration.getRemotePort()));
        //checkSeparateOSC.setSelected(configuration.getSendingSingleParameters());
        try {
            table.setDefaultRenderer(Class.forName("java.lang.Integer"), renderer);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(OscSynthConfigurationFrame2.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

   protected void setConfigurationFromForm() {
        boolean[] discrete = new boolean[model.numParams];
        int i = 0;
        for (boolean dd : model.isDiscrete) {
            discrete[i++] = dd;
        }

        i = 0;
        boolean[] dist = new boolean[model.numParams];
        for (boolean dd : model.isDistribution) {
            if (model.isDiscrete.get(i))
                dist[i] = dd;
            else
                dist[i] = false;
            i++;
        }

        i = 0;
        int[] max = new int[model.numParams];
        for (int dd : model.maxValue) {
            if (model.isDiscrete.get(i))
                max[i] = dd;
            else
                max[i] = 0;
            i++;
        }

        //Place info into configuration passed to us by outer system
        configuration.setNumParams(model.numParams);
        configuration.setNames(model.name.toArray(new String[0]));
        configuration.setDiscrete(discrete);
        configuration.setDistribution(dist);
        configuration.setMaxVals(max);
       // configuration.setSendingSingleParameters(checkSeparateOSC.isSelected());
       
        configuration.setUseRemoteHost(checkRemote.isSelected());
        configuration.setRemoteHostName(textRemoteHost.getText());
        int port = 0;
        try {
            port = Integer.parseInt(textOscPort.getText());
            configuration.setRemotePort(port);
        } catch (NumberFormatException ex) {
            Logger.getLogger(OscSynthConfigurationFrame2.class.getName()).log(Level.WARNING, "Invalid osc synth port of " + textOscPort.getText());
            textOscPort.setText(Integer.toString(configuration.getRemotePort()));
       }
        
        this.dispose();
   }


    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        scrollTable = new javax.swing.JScrollPane();
        buttonDelete = new javax.swing.JButton();
        buttonAdd = new javax.swing.JButton();
        buttonMoveUp = new javax.swing.JButton();
        buttonMoveDown = new javax.swing.JButton();
        buttonOK = new javax.swing.JButton();
        buttonCancel = new javax.swing.JButton();
        checkRemote = new javax.swing.JCheckBox();
        textRemoteHost = new javax.swing.JTextField();
        textOscPort = new javax.swing.JTextField();
        jLabel1 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        buttonDelete.setText("Delete selected");
        buttonDelete.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonDeleteActionPerformed(evt);
            }
        });

        buttonAdd.setText("Add parameter");
        buttonAdd.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonAddActionPerformed(evt);
            }
        });

        buttonMoveUp.setText("move up");
        buttonMoveUp.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonMoveUpActionPerformed(evt);
            }
        });

        buttonMoveDown.setText("move down");
        buttonMoveDown.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonMoveDownActionPerformed(evt);
            }
        });

        buttonOK.setText("OK");
        buttonOK.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonOKActionPerformed(evt);
            }
        });

        buttonCancel.setText("Cancel");
        buttonCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonCancelActionPerformed(evt);
            }
        });

        checkRemote.setText("Send to remote host");
        checkRemote.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                checkRemoteActionPerformed(evt);
            }
        });

        textRemoteHost.setText("Edgard.local");

        textOscPort.setText("12000");

        jLabel1.setText("Send OSC to port:");

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(buttonDelete)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(buttonAdd)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 313, Short.MAX_VALUE)
                .add(buttonCancel)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(buttonOK)
                .addContainerGap())
            .add(layout.createSequentialGroup()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(checkRemote)
                    .add(layout.createSequentialGroup()
                        .addContainerGap()
                        .add(textRemoteHost, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 136, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(layout.createSequentialGroup()
                        .addContainerGap()
                        .add(textOscPort, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 136, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                        .add(buttonMoveUp, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .add(buttonMoveDown))
                    .add(layout.createSequentialGroup()
                        .add(11, 11, 11)
                        .add(jLabel1)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(scrollTable, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 595, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(138, 138, 138)
                        .add(buttonMoveUp)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(buttonMoveDown)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(jLabel1)
                        .add(2, 2, 2)
                        .add(textOscPort, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 28, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(checkRemote)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(textRemoteHost, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(scrollTable, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 412, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(buttonDelete)
                    .add(buttonAdd)
                    .add(buttonCancel)
                    .add(buttonOK)))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void buttonDeleteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDeleteActionPerformed
        model.deleteRows(table.getSelectedRows());
        table.repaint();
}//GEN-LAST:event_buttonDeleteActionPerformed

    private void buttonAddActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAddActionPerformed
        model.addRow();
}//GEN-LAST:event_buttonAddActionPerformed

    private void buttonMoveUpActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveUpActionPerformed
        if (table.getSelectedRow() == -1 || table.getSelectedRow() == 0) {
            return;
        }
        int row = table.getSelectedRow();
        model.moveUp(row);
        table.getSelectionModel().setSelectionInterval(row - 1, row - 1);

}//GEN-LAST:event_buttonMoveUpActionPerformed

    private void buttonMoveDownActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveDownActionPerformed
        if (table.getSelectedRow() == -1 || table.getSelectedRow() == model.getRowCount() - 1) {
            return;
        }
        int row = table.getSelectedRow();
        model.moveDown(row);
        table.getSelectionModel().setSelectionInterval(row + 1, row + 1);
    }//GEN-LAST:event_buttonMoveDownActionPerformed

    private void buttonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOKActionPerformed
        setConfigurationFromForm();
        this.dispose();
    }//GEN-LAST:event_buttonOKActionPerformed

    private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
        this.dispose();
}//GEN-LAST:event_buttonCancelActionPerformed

    private void checkRemoteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkRemoteActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_checkRemoteActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {

                //new OscSynthConfigurationFrame2(0, null, null, null, null).setVisible(true);

                int n = 2;
                String[] names = {"Param 1", "P2"};
                boolean[] isDiscretes = {true, false};
                boolean[] isDistributions = {true, true};
                int[] maxValues = {3, 4};
                OscSynthConfiguration c = new OscSynthConfiguration(n, names, isDiscretes, isDistributions, maxValues);

                new OscSynthConfigurationFrame2(c).setVisible(true);
            //public OscSynthConfigurationFrame2(int n, String[] names, boolean[] isDiscretes, boolean[] isDistributions, int[] maxValues) {


            /*   try {
            // Thread.sleep(1000);
            //       new DataViewer().setVisible(true);
            } catch (InterruptedException ex) {
            Logger.getLogger(PlayalongScoreViewer.class.getName()).log(Level.SEVERE, null, ex);
            } */



            //       new DataViewer().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonAdd;
    private javax.swing.JButton buttonCancel;
    private javax.swing.JButton buttonDelete;
    private javax.swing.JButton buttonMoveDown;
    private javax.swing.JButton buttonMoveUp;
    private javax.swing.JButton buttonOK;
    private javax.swing.JCheckBox checkRemote;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane scrollTable;
    private javax.swing.JTextField textOscPort;
    private javax.swing.JTextField textRemoteHost;
    // End of variables declaration//GEN-END:variables
    private javax.swing.JTable table;
    private OscSynthTableModel model;
    //  private MainGUI gui;

    private void populateTable(OscSynthConfiguration c) {
        
        model = new OscSynthTableModel(c.getNumParams(), c.getParamNames(), c.getIsDiscrete(), c.getIsDistribution(), c.getMaxValue());
        table = new JTable(model);
        // table.getCellRenderer(0, 0).
        scrollTable.setViewportView(table);
        setTableColumns();
      /*  table.addPropertyChangeListener(new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent evt) {
                tablePropertyChanged(evt);
            }
        }); */
    }

    private void setTableColumns() {
        // table.getColumnModel().get
        table.getColumnModel().getColumn(0).setPreferredWidth(30);
        table.getColumnModel().getColumn(0).setMinWidth(10);
        table.getColumnModel().getColumn(0).setMaxWidth(30);

        table.getColumnModel().getColumn(1).setPreferredWidth(150);
        table.getColumnModel().getColumn(1).setMinWidth(50);
        table.getColumnModel().getColumn(1).setMaxWidth(200);
        table.getColumnModel().getColumn(2).setPreferredWidth(70);
        table.getColumnModel().getColumn(2).setMinWidth(70);
        table.getColumnModel().getColumn(2).setMaxWidth(70);

        table.getColumnModel().getColumn(3).setPreferredWidth(180);
        table.getColumnModel().getColumn(3).setMinWidth(70);
        table.getColumnModel().getColumn(3).setMaxWidth(180);
        table.getColumnModel().getColumn(4).setPreferredWidth(70);
        table.getColumnModel().getColumn(4).setMinWidth(70);
    }

    
}
class MySynthConfigRenderer extends DefaultTableCellRenderer {

    //   int specialRow = -1;
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column) {
        Component cell = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        if (column == 4 && !(Boolean) (table.getValueAt(row, 2))) {
            cell.setForeground(Color.GRAY);
        } else {
            cell.setForeground(Color.BLACK);
        }

        return cell;
    }

    /*    public void setSpecialRow(int r) {
    specialRow = r;
    } */
}

class OscSynthTableModel extends AbstractTableModel {

    private String[] columnNames;
    //  private Object[][] data;
    int numParams;
    LinkedList<String> name = new LinkedList<String>();
    LinkedList<Boolean> isDiscrete = new LinkedList<Boolean>();
    LinkedList<Boolean> isDistribution = new LinkedList<Boolean>();
    LinkedList<Integer> maxValue = new LinkedList<Integer>();

    public OscSynthTableModel(int n, String[] names, boolean[] isDiscretes, boolean[] isDistributions, int[] maxValues) {
        this.numParams = n;
        if (n > 0) {
            for (int i = 0; i < numParams; i++) {
                name.add(names[i]);
                isDiscrete.add(isDiscretes[i]);
                if (isDiscretes[i]) {
                    isDistribution.add(isDistributions[i]);
                    maxValue.add(maxValues[i]);
                } else {
                    isDistribution.add(false);
                    maxValue.add(0);
                }
            }
        }

        columnNames = new String[5];
        columnNames[0] = "#";
        columnNames[1] = "Name";
        columnNames[2] = "Discrete?";
        columnNames[3] = "Distribution?\n (Discrete only)";
        columnNames[4] = "Max value (Discrete only)";

    }

    public int getColumnCount() {
        return columnNames.length;
    }

    public int getRowCount() {
        return numParams;
    }

    public void addRow() {
        numParams++;
        name.add("Param" + numParams);
        isDiscrete.add(true);
        isDistribution.add(false);
        maxValue.add(1);
        fireTableRowsInserted(numParams - 1, numParams - 1);

    }

    @Override
    public String getColumnName(int col) {
        return columnNames[col];
    }

    public Object getValueAt(int row, int col) {
        if (row < 0 || row >= numParams) {
            return null;
        }
        if (col == 0) {
            return row + 1;
        } else if (col == 1) {
            return name.get(row);
        } else if (col == 2) {
            return isDiscrete.get(row);
        } else if (col == 3) {
            if (isDiscrete.get(row)) {
                return isDistribution.get(row);
            } else {
                return false;
            }
        } else {
            if (isDiscrete.get(row)) {
                return maxValue.get(row);
            } else {
                return 0;
            }
        }
    }

    @Override
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    @Override
    public boolean isCellEditable(int row, int col) {
        if (col == 0) {
            return false;
        }
        if (!isDiscrete.get(row)) {
            if (col == 3 || col == 4) {
                return false;
            }
        }
        return true;
    }


    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    public void setValueAt(Object value, int row, int col) {
        //Check it's legal:
        if (col == 1 && value instanceof String) {
            name.set(row, (String) value);
            fireTableCellUpdated(row, col);
        } else if (col == 2 && value instanceof Boolean) {
            isDiscrete.set(row, (Boolean) value);
            fireTableCellUpdated(row, 2);
            fireTableCellUpdated(row, 3);
            fireTableCellUpdated(row, 4);

            if (isDiscrete.get(row)) {
                if (maxValue.get(row) <= 0) {
                    maxValue.set(row, 1);
                }
            }

        } else if (col == 3 && value instanceof Boolean) {
            isDistribution.set(row, (Boolean) value);
            fireTableCellUpdated(row, col);
        } else if (col == 4 && value instanceof Integer) {
            int v = (Integer) value;
            if (v > 0) {
                maxValue.set(row, v);
            }
            fireTableCellUpdated(row, col);
        }
    }

    void colorSpecial(int playingRow) {
        //throw new UnsupportedOperationException("Not yet implemented");
    }

    void deleteRows(int[] selectedRows) {
        for (int j = selectedRows.length - 1; j >= 0; j--) {
            name.remove(selectedRows[j]);
            isDiscrete.remove(selectedRows[j]);
            isDistribution.remove(selectedRows[j]);
            maxValue.remove(selectedRows[j]);
            numParams--;
            fireTableRowsDeleted(selectedRows[j], selectedRows[j]);
        }
    }

    void moveDown(int row) {
        if (row >= numParams) {
            return;
        }
        swap(row, row + 1);
    }

    void moveUp(int row) {
        if (row <= 0) {
            return;
        }
        swap(row, row - 1);
    }

    void swap(int row1, int row2) {
        boolean tmp = isDiscrete.get(row1);
        isDiscrete.set(row1, isDiscrete.get(row2));
        isDiscrete.set(row2, tmp);

        tmp = isDistribution.get(row1);
        isDistribution.set(row1, isDistribution.get(row2));
        isDistribution.set(row2, tmp);

        int tmpi = maxValue.get(row1);
        maxValue.set(row1, maxValue.get(row2));
        maxValue.set(row2, tmpi);

        String tmps = name.get(row1);
        name.set(row1, name.get(row2));
        name.set(row2, tmps);


        fireTableRowsUpdated(row1, row1);
        fireTableRowsUpdated(row2, row2);

    }
}

